package com.yida.gwj.expend.outside.handler;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.yida.common.core.constant.SecurityConstants;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.redis.service.RedisService;
import com.yida.gwj.api.domain.GwjConfBusinessFlag;
import com.yida.gwj.api.domain.GwjConfStep;
import com.yida.gwj.api.service.RemoteGwjConfigService;
import com.yida.gwj.common.enums.GwjBusinessFlagType;
import com.yida.gwj.common.enums.GwjBusinessLogResult;
import com.yida.gwj.expend.outside.config.MaintenanceFundsBusinessConfiguration;
import com.yida.gwj.expend.outside.domain.GwjMaintenanceFundsBusiness;
import com.yida.gwj.expend.outside.domain.GwjMaintenanceFundsBusinessLog;
import com.yida.gwj.expend.outside.domain.message.MqBaseResult;
import com.yida.gwj.expend.outside.domain.message.PreAcceptSubmitMessage;
import com.yida.gwj.expend.outside.enums.BusinessServerStatusEnum;
import com.yida.gwj.expend.outside.enums.BusinessStatusEnum;
import com.yida.gwj.expend.outside.enums.BusinessTypeEnum;
import com.yida.gwj.expend.outside.enums.FlagStatusEnum;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessBuildService;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessCommunityService;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessHouseService;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessInfoService;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessLogService;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessOwnerService;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/**
 * 首次提交消费
 *
 * @author liangp
 * @date 2023/03/01
 */
@Component
@RocketMQMessageListener(topic = "${gwj.expend-appropriate.topic}", consumerGroup = "${gwj.expend-appropriate.group.outer}", selectorExpression = "${gwj.expend-appropriate.tag.formal-submit}", messageModel = MessageModel.CLUSTERING)
public class ExpendOuterAppropriateListenerHandler implements RocketMQListener<MessageExt>, RocketMQPushConsumerLifecycleListener {

    private final Logger log = LoggerFactory.getLogger(ExpendOuterAppropriateListenerHandler.class);
    private final String cache = "gwj:" + MaintenanceFundsBusinessConfiguration.maintenanceFundsBusinessAppropriateTopic + ":mq:";

    @Autowired
    private RedisService redisService;
    @Autowired
    private IGwjMaintenanceFundsBusinessService maintenanceFundsBusinessService;
    @Autowired
    private IGwjMaintenanceFundsBusinessHouseService maintenanceFundsBusinessHouseService;
    @Autowired
    private IGwjMaintenanceFundsBusinessInfoService maintenanceFundsBusinessInfoService;
    @Autowired
    private IGwjMaintenanceFundsBusinessBuildService maintenanceFundsBusinessBuildService;
    @Autowired
    private IGwjMaintenanceFundsBusinessOwnerService maintenanceFundsBusinessOwnerService;
    @Autowired
    private IGwjMaintenanceFundsBusinessCommunityService maintenanceFundsBusinessCommunityService;
    @Autowired
    private IGwjMaintenanceFundsBusinessLogService maintenanceFundsBusinessLogService;
    @Autowired
    private RemoteGwjConfigService remoteGwjConfigService;
    @Autowired
    private MaintenanceFundsBusinessConfiguration maintenanceFundsBusinessConfiguration;

    /**
     * 消息接收处理方法
     *
     * @param message 消息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void onMessage(MessageExt message) {
        log.info("[MQ][OUTER][APPROPRIATE] topic -> [{}], tag -> [{}] 消息开始处理.....", message.getTopic(), message.getTags());
        TimeInterval timer = null;
        if (log.isDebugEnabled()) {
            timer = DateUtil.timer();
            log.debug("[MQ][OUTER][APPROPRIATE] 参数体 -> [{}]", message);
        }
        if (redisService.hasKey(cache + message.getKeys())) {
            log.error("当前消息已经消费,key值 -> [{}]", message.getKeys());
            return;
        }
        try {
            Optional<JSONObject> optionalJson = JSONUtil.toBean(StrUtil.utf8Str(message.getBody()), Optional.class);
            optionalJson.<ServiceException>orElseThrow(() -> {
                throw new ServiceException("MQ基础信息获取失败");
            });
            MqBaseResult mqBaseResult = JSONUtil.toBean(optionalJson.get(), MqBaseResult.class);
            if (ObjectUtil.equal(message.getTags(), maintenanceFundsBusinessConfiguration.appropriateTagProperties().getFormalSubmit())) {
                formalSubmit(mqBaseResult);
            }
            redisService.setCacheObject(cache + message.getKeys(), message.getKeys(), 1L, TimeUnit.DAYS);
            if (log.isDebugEnabled()) {
                log.debug("消费处理时间 [{}] 毫秒", timer.interval());
            }
            log.info("[MQ][OUTER][APPROPRIATE] topic -> [{}], tag -> [{}] 消息处理完成", message.getTopic(), message.getTags());
        } catch (Exception e) {
            log.error("公维金申请外网数据到内网数据获取失败 -> [{}]", e);
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 消息接受前置处理
     *
     * @param defaultMqPushConsumer
     */
    @Override
    public void prepareStart(DefaultMQPushConsumer defaultMqPushConsumer) {
        defaultMqPushConsumer.setMaxReconsumeTimes(1);
    }

    public void formalSubmit(MqBaseResult mqBaseResult) {
        PreAcceptSubmitMessage acceptSubmitMessage = JSONUtil.toBean(mqBaseResult.getJsonMsg(), PreAcceptSubmitMessage.class);
        if (ObjectUtil.isNull(acceptSubmitMessage)) {
            throw new ServiceException("PreAcceptSubmitMessage转换失败");
        }
        // 参数校验
        acceptSubmitMessage.checkNull();
        GwjMaintenanceFundsBusiness maintenanceFundsBusiness = acceptSubmitMessage.getMaintenanceFundsBusiness();

        maintenanceFundsBusiness.setBizId(null);
        maintenanceFundsBusiness.setCurrentOperId(null);
        maintenanceFundsBusiness.setCurrentOperName(null);
        maintenanceFundsBusiness.setStatus(BusinessStatusEnum.SAVE.getCode());
        maintenanceFundsBusiness.setSupplementFlag(FlagStatusEnum.FAL.getCode());
        maintenanceFundsBusiness.setServerIdentification(IdUtil.getSnowflakeNextIdStr());
        maintenanceFundsBusiness.setType(BusinessTypeEnum.APPROPRIATE_PREPARE.getCode());
        maintenanceFundsBusiness.setServerStatus(BusinessServerStatusEnum.NORMAL.getCode());
        maintenanceFundsBusiness.setBizFlagId(GwjBusinessFlagType.EXPEND_OUTSIDE_APPROPRIATE.getCode());
        maintenanceFundsBusiness.setFinancialJournalFlag(FlagStatusEnum.FAL.getCode());
        try {
            GwjConfBusinessFlag confBusinessFlag = remoteGwjConfigService.selectGwjConfBusinessFlagByBizFlagId(GwjBusinessFlagType.EXPEND_OUTSIDE_APPROPRIATE.getCode(), SecurityConstants.INNER).getData();
            if (ObjectUtil.isNull(confBusinessFlag)) {
                throw new ServiceException("GwjConfBusinessFlag列表为空");
            }
            maintenanceFundsBusiness.setFlowId(confBusinessFlag.getFlowId());
            GwjConfStep gwjConfStep = remoteGwjConfigService.getFirstStep(GwjBusinessFlagType.EXPEND_OUTSIDE_APPROPRIATE.getCode(), SecurityConstants.INNER).getData();
            if (ObjectUtil.isNull(gwjConfStep)) {
                throw new ServiceException("GwjConfStep为空");
            }
            maintenanceFundsBusiness.setStepId(gwjConfStep.getStepId());
        } catch (Exception e) {
            log.error("GwjConfStep获取异常 -> [{}]", e);
            throw new ServiceException("获取GwjConfStep异常");
        }

        maintenanceFundsBusinessService.insertGwjMaintenanceFundsBusiness(maintenanceFundsBusiness);
        acceptSubmitMessage.getMaintenanceFundsBusinessBuildList().forEach(build -> {
            build.setBizId(maintenanceFundsBusiness.getBizId());
        });
        if (ObjectUtil.equal(maintenanceFundsBusinessBuildService.insertBatchGwjMaintenanceFundsBusinessBuild(acceptSubmitMessage.getMaintenanceFundsBusinessBuildList()), FlagStatusEnum.FAL.getCode())) {
            throw new ServiceException("GwjMaintenanceFundsBusinessBuild新增失败");
        }
        acceptSubmitMessage.getMaintenanceFundsBusinessCommunity().setBizId(maintenanceFundsBusiness.getBizId());
        Optional.ofNullable(maintenanceFundsBusinessCommunityService.insertGwjMaintenanceFundsBusinessCommunity(acceptSubmitMessage.getMaintenanceFundsBusinessCommunity())).<ServiceException>orElseThrow(() -> {
            throw new ServiceException("GwjMaintenanceFundsBusinessCommunity新增失败");
        });
        acceptSubmitMessage.getMaintenanceFundsBusinessHouseList().forEach(house -> {
            house.setBizId(maintenanceFundsBusiness.getBizId());
        });
        if (ObjectUtil.equal(maintenanceFundsBusinessHouseService.insertBatchGwjMaintenanceFundsBusinessHouse(acceptSubmitMessage.getMaintenanceFundsBusinessHouseList()), FlagStatusEnum.FAL.getCode())) {
            throw new ServiceException("GwjMaintenanceFundsBusinessHouse新增失败");
        }
        acceptSubmitMessage.getMaintenanceFundsBusinessInfo().setBizId(maintenanceFundsBusiness.getBizId());
        acceptSubmitMessage.getMaintenanceFundsBusinessInfo().setTotalSettlementAmount(BigDecimal.ZERO);
        acceptSubmitMessage.getMaintenanceFundsBusinessInfo().setTotalAllocatedSettlementAmount(BigDecimal.ZERO);
        acceptSubmitMessage.getMaintenanceFundsBusinessInfo().setSecondAppropriationAmount(BigDecimal.ZERO);
        acceptSubmitMessage.getMaintenanceFundsBusinessInfo().setActualAllocatedSettlementAmount(BigDecimal.ZERO);
        acceptSubmitMessage.getMaintenanceFundsBusinessInfo().setActualAllocatedTime(null);
        Optional.ofNullable(maintenanceFundsBusinessInfoService.insertGwjMaintenanceFundsBusinessInfo(acceptSubmitMessage.getMaintenanceFundsBusinessInfo())).<ServiceException>orElseThrow(() -> {
            throw new ServiceException("GwjMaintenanceFundsBusinessInfo新增失败");
        });
        acceptSubmitMessage.getMaintenanceFundsBusinessOwnerList().forEach(owner -> {
            owner.setBizId(maintenanceFundsBusiness.getBizId());
        });
        if (ObjectUtil.equal(maintenanceFundsBusinessOwnerService.insertBatchGwjMaintenanceFundsBusinessOwner(acceptSubmitMessage.getMaintenanceFundsBusinessOwnerList()), FlagStatusEnum.FAL.getCode())) {
            throw new ServiceException("GwjMaintenanceFundsBusinessOwner新增失败");
        }
        int insertFlag = maintenanceFundsBusinessLogService.insertGwjMaintenanceFundsBusinessLog(new GwjMaintenanceFundsBusinessLog() {
            /**
             *
             */
            private static final long serialVersionUID = 3397520309291492238L;

            {
                setStepId(maintenanceFundsBusiness.getStepId());
                setBizId(maintenanceFundsBusiness.getBizId());
                setAcceptTime(LocalDateTime.now());
                setResult(GwjBusinessLogResult.SAVE.getCode());
                setOperId(acceptSubmitMessage.getMaintenanceFundsBusiness().getApplicantUserId());
                setOperName(acceptSubmitMessage.getMaintenanceFundsBusiness().getApplicantUserName());
            }
        });
        if (ObjectUtil.notEqual(insertFlag, FlagStatusEnum.SUC.getCode())) {
            throw new ServiceException("GwjMaintenanceFundsBusinessLog新增失败");
        }
    }
}
